package ua.kratik.seabattle.dao;

import java.util.Iterator;
import java.util.List;

import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

public abstract class GenericDAO<D extends DataObject> implements BasicDAO<D> {

	private Logger logger = LoggerFactory.getLogger(this.getClass());
	
	private Class<D> dtoClass;
	
	@Autowired
	private SessionFactory sf;
	
	protected GenericDAO(Class<D> dtoClass){
		this.dtoClass = dtoClass;
	}
	
	public void add(D dto) {
		sf.getCurrentSession().save(dto);
	}

	public void addAll(List<D> dtos) {
		Iterator<D> it = dtos.iterator();
		while(it.hasNext()){
			this.add(it.next());
		}
	}

	public void remove(D dto) {
		sf.getCurrentSession().delete(dto);
	}

	public void removeById(Integer id) {
		//Casts an object to the class or interface represented by this Class object.
		this.remove(this.findById(id));
	}

	public void removeAll(List<D> dtos) {
		Iterator<D> it = dtos.iterator();
		while(it.hasNext()){
			this.remove(it.next());
		}
	}

	/**
	 * Return the persistent instance of the given id, or null if there 
	 * is no such persistent instance. (If the instance is already associated 
	 * with the session, return that instance. This method never returns an 
	 * uninitialized instance.)
	 */
	public D findById(Integer id) {
		return dtoClass.cast(sf.getCurrentSession().get(dtoClass, id));
	}

	@SuppressWarnings("unchecked")
	public List<D> findAll() {
		logger.debug("trying to find all items");
		try{
			return sf.getCurrentSession().createCriteria(dtoClass).list();
		}catch(Exception ex){
			logger.error("error while downloading list of items in table", ex);
			logger.error("sf == null: " + (sf == null));
			return null;
		}
	}

	public void update(D dto) {
		throw new UnsupportedOperationException("Not implemented yet");
		
	}

	public void refresh(D dto) {
		sf.getCurrentSession().refresh(dto);
	}

	protected SessionFactory getSf() {
		return sf;
	}

	protected void setSf(SessionFactory sf) {
		this.sf = sf;
	}

}
